#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NONSTDC_NO_DEPRECATE
#include"StringPool.h"
#include"variable.h"
#include"DependencyInstance.h"
#include"DependencyReader.h"
#include"CONLLReader.h"
#include"RelationalFeature.h"
#include"Util.h"
using namespace std;

CONLLReader::CONLLReader(bool discourseMode, bool labeled, bool hasEnd) : DependencyReader(){
	this->discourseMode = discourseMode;
	this->labeled = labeled;
	this->hasEnd = hasEnd;
}

bool CONLLReader::fileContainsLabels(const char *filename){
	FILE* in = fopen(filename, "r");
	char line[10000];
	fgets(line, 10000, in);
	string tmp = string(line);
	string* s = pool->get(tmp);
	fclose(in);
	string* str = Util::trim(s);
	pool->push_back(s);
	if(str->length() > 0){
		pool->push_back(str);
		return true;
	}
	else{
		pool->push_back(str);
		return false;
	}
}

DependencyInstance* CONLLReader::getNext(){
	vector<vector<string*>*>* lineList = new vector<vector<string*>*>();
	char line[10000];
	string* str;
	if(fgets(line, 10000, inputReader) == NULL){
		return NULL;
	}
	int str_len = (int)(strlen(line));
	line[str_len - 1] = '\0';
	while(!feof(inputReader) && !(str_len == 1) && !(line[0] == '*')){
		string tmp = string(line);
		str = pool->get(tmp);
		vector<string*>* aaa = Util::split(str, '\t');
		lineList->push_back(aaa);
		pool->push_back(str);
		if(fgets(line, 10000, inputReader) == NULL){
			line[0] = '\0';
			break;
		}
		str_len = (int)(strlen(line));
		line[str_len - 1] = '\0';
	}
	
	int length = (int)lineList->size();

	if(length == 0){
		delete(lineList);
		return NULL;
	}

	vector<string*>* forms = new vector<string*>(length + 1);
	vector<string*>* lemmas = new vector<string*>(length + 1);
	vector<string*>* cpos = new vector<string*>(length + 1);
	vector<string*>* pos = new vector<string*>(length + 1);
	vector<string*>* deprels = new vector<string*>(length + 1);
	vector<vector<string*>*>* feats = new vector<vector<string*>*>(length + 1);
	vector<int>* heads = new vector<int>(length + 1);
	
	string tmp = string("<root>");
	(*forms)[0] = pool->get(tmp);
	tmp = string("<root-LEMMA>");
	(*lemmas)[0] = pool->get(tmp);
	tmp = string("<root-CPOS>");
	(*cpos)[0] = pool->get(tmp);
	tmp = string("<root-POS>");
	(*pos)[0] = pool->get(tmp);
	tmp = string("<no-type>");
	(*deprels)[0] = pool->get(tmp);
	(*heads)[0] = -1;
	
	for(int i = 0; i < length; i++){
		vector<string*>* info = (*lineList)[i];
		(*forms)[i + 1] = normalize((*info)[1]);
		(*lemmas)[i + 1] = normalize((*info)[2]);
		tmp = string(*((*info)[3]));
		(*cpos)[i + 1] = pool->get(tmp);
		tmp = string(*((*info)[4]));
		(*pos)[i + 1] = pool->get(tmp);
		(*feats)[i + 1] = Util::split((*info)[5], '|');
		string tmp1 = string(*((*info)[7]));
		string tmp2 = string("<no-type>");
		(*deprels)[i + 1] = labeled ? pool->get(tmp1) : pool->get(tmp2);
		(*heads)[i + 1] = Util::stringToInt((*info)[6]);
		
		vector<string*>::iterator iter;
		for(iter = info->begin(); iter != info->end(); iter++){
			//cout<<(*iter)->c_str()<<" ";
			pool->push_back(*iter);
		}
		//cout<<endl;
		delete(info);
	}
	delete(lineList);
	
	int len_1 = (int)((*feats)[1]->size());
	(*feats)[0] = new vector<string*>(len_1);
	for(int i = 0; i < len_1; i++){
		string* ii = Util::intToString(i);
		tmp = string("<root-feat>" + *ii);
		(*(*feats)[0])[i] = pool->get(tmp);
		pool->push_back(ii);
	}
	
	if(hasEnd){
		tmp = string("<end>");
		forms->push_back(pool->get(tmp));
		tmp = string("<end-LEMMA>");
		lemmas->push_back(pool->get(tmp));
		tmp = string("<end-CPOS>");
		cpos->push_back(pool->get(tmp));
		tmp = string("<end-POS>");
		pos->push_back(pool->get(tmp));
		tmp = string("<no-type>");
		deprels->push_back(pool->get(tmp));
		heads->push_back(0);
		feats->push_back(new vector<string*>(len_1));
		int endId = (int)(forms->size()) - 1;
		for(int i = 0; i < len_1; i++){
			string* ii = Util::intToString(i);
			tmp = string("<end-feat>" + *ii);
			(*(*feats)[endId])[i] = pool->get(tmp);
			pool->push_back(ii);
		}
	}

	if(discourseMode){
		int len_dis = (int)((*feats)[0]->size());
		vector<vector<string*>*>* extended_feats = new vector<vector<string*>*>(len_dis);
		for(int i = 0; i < len_dis; i++){
			(*extended_feats)[i] = new vector<string*>(length + 1);
		}
		int length = (int)extended_feats->size();
		for(int i = 0; i < length; i++){
			for(int j = 0; j< length + 1; j++){
				(*(*extended_feats)[i])[j] = (*(*feats)[j])[i];
			}
		}
		feats = extended_feats;
		vector<vector<string*>*>::iterator iter;
		for(iter = extended_feats->begin(); iter != extended_feats->end(); iter++){
			delete(*iter);
		}
		delete(extended_feats);
	}

	vector<RelationalFeature*>* rfeats = new vector<RelationalFeature*>();
	
	while(!(strcmp(line, "") == 0)){
	  tmp = string(line);
		string* del = pool->get(tmp);
		rfeats->push_back(new RelationalFeature(length, del, inputReader));
		pool->push_back(del);
		fgets(line, 10000, inputReader);
		str_len = (int)(strlen(line));
		line[str_len - 1] = '\0';
	}
	

	return new DependencyInstance(forms, lemmas, cpos, pos, deprels, feats, heads, rfeats);
}
